#include <Windows.h>
#include <stdlib.h>
#include <stdio.h>


void dot(float *A, float *B, float *C, int x, int y, int k, int col){
    register float c00,c01,c10,c11;
    c00 = 0.0;
    c01  = 0.0;
    c10  = 0.0;
    c11  = 0.0;
    for (int c = 0; c < k; c++){
        int xk = x*k + c;
        int yk = c*k + y;
        int yk1 = c*k + y + 1;
        int xk1 = (x+1)*k + c;
        c00 += A[xk] * B[yk];
        c01 += A[xk] * B[yk1];
        c10 += A[xk1] * B[yk];
        c11 += A[xk1] * B[yk1];
    }
    int xcol = x*col + y;
    int ycol = (x+1)*col + y;
    C[xcol] = c00;
    C[xcol + 1] = c01;
    C[ycol] = c10;
    C[ycol + 1] = c11;
}

void gemm(float *A, float *B, float *C, int m, int n, int k){
    for (int i = 0; i < m; i+=2){
        for (int j = 0; j < n; j+=2){
            dot(A, B, C, i, j, k, n);
        }
    }
}

int main(){
    int m = 1024, n = 1024, k = 1024;
    float *A = (float *)malloc(m*k*sizeof(float));
    float *B = (float *)malloc(k*n*sizeof(float));
    float *C = (float *)malloc(m*n*sizeof(float));

    for (int i = 0; i < m*k; i++){
        A[i] = 1.0f;
    }

    for (int i = 0; i < k*n; i++){
        B[i] = 1.0f;
    }

    for (int i = 0; i < m*n; i++){
        C[i] = 0.0f;
    }

    DWORD start_t, end_t;

    start_t = GetTickCount();
    
    gemm(A, B, C, m , n, k);

    end_t = GetTickCount();

    double time = (end_t - start_t)/1e+3;
    printf("time: %lf s\n", time);

    double flops = 2.0 * m * n * k * 1e-9;
    printf("flops: %lf Gflops\n", flops/time);

    free(A);
    free(B);
    free(C);

    return 0;
}